using System;
using System.Data;
using System.Linq;
using NUnit.Framework;
using PropertyExpression.ReactiveRelation.Test.Common;
using PropertyExpression.ReactiveRelation.Values;

namespace PropertyExpression.ReactiveRelation.Test
{
    [TestFixture]
    public class TreeNodeTest: BaseDbTest
    {
        protected override void DbClean()
        {
            DataContextProviderHolder.Provider
                .Execute(context =>
                             {
                                 context.TreeNodes.DeleteAll();

                                 context.SubmitChanges();
                             },
                         IsolationLevel.Serializable);
        }

        [Test]
        public void Test()
        {
            var contextProvider = new ContextProvider(
                registrator =>
                registrator.Register<TreeNode>(
                    binder => binder._(_ => _.Total)(
                                  it => it._(_ => _.TreeNodes)
                                            .Sum(treeNode => treeNode._(_ => _.Total))
                                  )
                    )
                );

            const IsolationLevel isolationLevel = IsolationLevel.Serializable;

            contextProvider.Execute(                
                (context, calcExecutor) => 
                    {
                        var treeNode1 = context.Create<TreeNode>(calcExecutor);
                        treeNode1._(_ => _.TreeNodeId)(1);

                        var treeNode11 = context.Create<TreeNode>(calcExecutor);
                        treeNode11._(_ => _.TreeNodeId)(11);
                        treeNode11._(_ => _.TreeNode1).OverloadCall(treeNode1);

                        var treeNode12 = context.Create<TreeNode>(calcExecutor);
                        treeNode12._(_ => _.TreeNodeId)(12);
                        treeNode12._(_ => _.TreeNode1).OverloadCall(treeNode1);

                        var treeNode111 = context.Create<TreeNode>(calcExecutor);
                        treeNode111._(_ => _.TreeNodeId)(111);
                        treeNode111._(_ => _.TreeNode1).OverloadCall(treeNode11);

                        var treeNode112 = context.Create<TreeNode>(calcExecutor);
                        treeNode112._(_ => _.TreeNodeId)(112);
                        treeNode112._(_ => _.TreeNode1).OverloadCall(treeNode11);

                        var treeNode121 = context.Create<TreeNode>(calcExecutor);
                        treeNode121._(_ => _.TreeNodeId)(121);
                        treeNode121._(_ => _.TreeNode1).OverloadCall(treeNode12);

                        context.SubmitChanges();
                    }, isolationLevel);

            contextProvider.Execute(
                (context, calcExecutor) => 
                    {
                        Func<int, ICalcInitiator<TreeNode>> getTreeNodeFunc =
                            id => context.TreeNodes.Single(_ => _.TreeNodeId == id).Couple(calcExecutor);

                        getTreeNodeFunc(111)._( _ => _.Total)(4);

                        getTreeNodeFunc(121)._( _ => _.Total)( 3);

                        getTreeNodeFunc(12)._( _ => _.Total)(77);

                        getTreeNodeFunc(112)._( _ => _.Total)(354);

                        Assert.AreEqual(435, getTreeNodeFunc(1).Entity.Total);

                        context.SubmitChanges();
                    }, isolationLevel);
        }
    }
}